/**
 * @author roy
 * @desc   royui
 * @time   2022/05/31
 */
let $prop = null
let Royui = function(obj) {
    this.elem = document.querySelectorAll(obj);
    $prop = this.elem
};
let $config = null;
Royui.prototype.treeTable = function($options) {
    $config = {
        cols: $options.cols ?? undefined, // 列参数
        url: $options.url ?? undefined, // url模式
        method: $options.method ?? 'get', // url请求方式
        where: $options.where ?? undefined, // url 请求参数
        data: $options.data ?? undefined, // 直接赋值数据
        is_cache: $options.is_cache ?? true, // 是否缓存
        sort_field: $options.sort_field ?? undefined, // 排序字段
        sort_type: $options.sort_type ?? 'desc', // 排序方式
        tree: {
            primary_key: $options.tree ? ($options.tree.primary_key ?? 'id') : 'id', // 主键名称
            iconIndex: $options.tree ? ($options.tree.iconIndex ?? undefined) : undefined, // 图标列的索引
            icon: $options.tree ? ($options.tree.icon ?? '<div class="royui-icon-triangle-r"></div>') : '', // 折叠图标
            loading_type: $options.tree ? ($options.tree.loading_type ?? 'circle') : 'circle' // loading 样式
        },
        paging: $options.paging ?? false, // 是否分页
        count: $options.count ?? 0, // 数据总条数
        show_count: $options.show_count ?? true, // 是否显示总条数
        pagesize: $options.pagesize ?? 20, // 默认每页显示条数
        is_size: $options.is_size ?? false, // 是否可选择每页大小
        size_arr: $options.size_arr ?? [10, 20, 30, 50], // 每页分页大小
        first_page: $options.first_page ?? true, // 是否开启首页按钮
        last_page: $options.last_page ?? true, // 是否开启尾页按钮
        next_page: $options.next_page ?? true, // 是否开启下一页
        prev_page: $options.prev_page ?? true, // 是否开启上一页
        show_pages: $options.show_pages ?? 5, // 最多显示页码数
        jump_to: $options.jump_to ?? false, // 是否显示跳转到
        checkbox: $options.checkbox ?? false, // 是否添加复选框
        onSelected: $options.onSelected ?? undefined, // 自定义选择函数
        onSelectAll: $options.onSelectAll ?? undefined, // 自定义全选函数
        onUpdated: $options.onUpdated ?? undefined, // 自定义修改成功后执行函数
        onDeleted: $options.onDeleted ?? undefined // 自定义删除成功后执行函数
    };
    let $is_ajax = false;
    if ($config.url && !$config.data) {
        let $where = $config.where ?? {}, $search = location.search;
        if ($search) {
            let $url_param = $search.substr(1);
            let $url_param_arr = $url_param.split('&');
            for ($m = 0; $m < $url_param_arr.length; $m++) {
                let $pitem = $url_param_arr[$m].split('=');
                $where[$pitem[0]] = decodeURI($pitem[1]);
            }
        }
        if ($config.sort_field) {
            $where['sort_field'] = $config.sort_field;
            $where['sort_type'] = $config.sort_type;
        }
        $.ajax({
            type: $config.method,
            dataType: 'json',
            cache: false,
            async: false,
            url: $config.url,
            data: $where,
            success: function($data) {
                if ($data.code === 200 || $data.code === 0 || $data.status === 0 || $data.status === 200) {
                    $config.data = $data.data;
                    $is_ajax = true;
                }
            },
            error: function() {
                throw '服务器异常';
            }
        })
    }
    if ($config.data === undefined || $config.data === null || $config.data === '' || $.type($config.data) !== 'array') {
        throw '数据异常';
    }
    $('head').append([
        '<style type="text/css">',
        '.royui-treetable{border:solid 1px #e7eaec;overflow:hidden;width:100%}',
        '.royui-treetable thead tr{background:#f5f5f6;border:0;border-bottom:solid 1px #e7eaec}',
        '.royui-treetable tbody tr:nth-of-type(even){background:#f9f9f9}',
        '.royui-treetable tbody tr:hover{background:#f5f5f6}',
        '.royui-treetable tbody .royui-hid{display:none}',
        '.royui-checkbox{display:inline-block;width:14px;height:14px;line-height:14px;border:solid 1px #cdcdcd;text-align:center;cursor:pointer}',
        '.royui-checkbox.is-checked{background:#409eff;border:solid 1px #409eff}',
        '.royui-checkbox-inner{display:inline-block;width:6px;height:10px;margin-bottom:3px;transform:rotate(45deg);border-right:solid 1px #fff;border-bottom:solid 1px #fff}',
        '.royui-checkbox-inner-all{display:inline-block;width:6px;height:0;margin-bottom:5px;border-top:solid 1px #fff;border-bottom:solid 1px #fff}',
        '.royui-treetable thead tr>th:first-child{text-align: center}',
        '.royui-treetable tbody tr>td:first-child{text-align: center}',
        '.royui-treetable th,.royui-treetable td{height:36px;text-align:left;font-size:14px;border-bottom:solid 1px #e7eaec}',
        '.royui-treetable td span{display:inline-block}',
        '.royui-icon-triangle-u{width:0;height:0;display:inline-block;margin-right:5px;cursor:pointer;border-width:0 6px 6px;border-style:solid;border-color:transparent transparent #333;}/* 向上 */',
        '.royui-icon-triangle-d{width:0;height:0;display:inline-block;margin-right:5px;cursor:pointer;border-width:6px 6px 0;border-style:solid;border-color:#333 transparent transparent;}/* 向下 */',
        '.royui-icon-triangle-l{width:0;height:0;display:inline-block;margin-right:5px;cursor:pointer;border-width:6px 6px 6px 0;border-style:solid;border-color:transparent #333 transparent transparent;}/* 向左 */',
        '.royui-icon-triangle-r{width:0;height:0;display:inline-block;margin-right:5px;cursor:pointer;border-width:6px 0 6px 6px;border-style:solid;border-color:transparent transparent transparent #333;}/* 向右 */',
        '.royui-button-a{font-size:12px;text-decoration:none;color:#3a6be0}',
        '.royui-loading{display:inline-block;margin-left:20px;vertical-align:middle}',
        '.royui-loading-line{width:60px;height:10px;border-radius:10px;background:linear-gradient(orange 0 0) 0/0% no-repeat lightblue;animation:load 1s infinite steps(10);}@keyframes load{100% {background-size:110%}}',
        '.royui-loading-circle{box-sizing:border-box;width:23px;height:23px;display:inline-block;border:3px solid #f3f3f3;border-top:3px solid #f00;border-radius:50%;animation:rotate-360 1s infinite linear}@keyframes rotate-360{0% {transform: rotate(0deg)} 100% {transform: rotate(360deg)}}',
        '.royui-loading-big{position:absolute;left:40%;top:30%;z-index:9999;display:block;box-sizing:border-box;width:50px;height:50px;display:inline-block;border:5px solid #f3f3f3;border-top:5px solid #a0f;border-radius:50%;animation:rotate-360 1s infinite linear}@keyframes rotate-360{0% {transform: rotate(0deg)} 100% {transform: rotate(360deg)}}',
        '</style>'
    ].join(''));
    if ($config.cols) {
        let $thisElem = this.elem;
        $(this.elem).attr({
            'cellpadding': 0,
            'cellspacing': 0
        }).addClass('royui-treetable');
        let $thead = '<thead><tr>';
        if ($config.checkbox) {
            $thead += '<th style="width: 50px;"><span class="royui-checkbox" onclick="checkAll(this)"><input type="checkbox" class="royui_checkbox_all royui-hid" /><span class="royui-checkbox-inner"></span></span></th>';
        } else {
            $thead += '<th style="width: 15px;"></th>'
        }
        $($config.cols).each(function($i, $col) {
            let $title_style = $col.title_style ? ' style="' + $col.title_style + '"' : '';
            let $triangle = '', $onclick = '';
            if ($col.is_sort) {
                let $search = location.search.substr(1);
                let $sc_arr = $search.split('&');
                $sc_arr.forEach(($v, $n, $ar) => {
                    let $v_a = $v.split('=');
                    if ($v_a[0] === 'sort_field' && $v_a[1] === $col.field) {
                        $triangle = ' &nbsp; <div class="sort royui-icon-triangle-d"></div>';
                    }
                    if ($triangle !== '' && $v_a[0] === 'sort_type' && $v_a[1] === 'asc') {
                        $triangle = ' &nbsp; <div class="sort royui-icon-triangle-u"></div>';
                    }
                })
                $onclick = ` onclick="clickTH(this,'${$col.field}')"`
            }
            $thead += `<th${$title_style}${$onclick}>${$col.title}${$triangle}</th>`
        });
        $thead += '</tr></thead>';
        $(this.elem).append($thead);
        let $tbody = '<tbody>';
        $($config.data).each(function($i, $item) {
            $tbody += '<tr>';
            if ($config.checkbox) {
                let strItem = JSON.stringify($item)
                $tbody += `<td style="text-align:center"><span class="royui-checkbox" onclick='checkItem(this, ${strItem})'><input type="checkbox" class="royui_checkbox royui-hid" value="${$item[$config.tree.primary_key]}" /><span class="royui-checkbox-inner"></span></span></td>`;
                if (typeof $config.onSelected === 'function') {
                    $($thisElem).on('click', '.royui-checkbox', function() {
                        if (parseInt($item[$config.tree.primary_key]) === parseInt($(this).find('input:checkbox').val())) {
                            $config.onSelected($item, this);
                        }
                    });
                }
            } else {
                $tbody += '<td style="width: 15px;"></td>'
            }
            $($config.cols).each(function($ii, $col) {
                let $icon = '', $tip = false, $hh = $item.has_children ?? false;
                if ($ii === $config.tree.iconIndex) {
                    $tip = true;
                    if ($hh) {
                        $icon = $config.tree.icon;
                    }
                }
                $tbody += createCol($col, 0, $item, $icon, $config.tree.primary_key, 0, $tip);
            });
            $tbody += '</tr>';
        });
        $tbody += '</tbody>';
        $(this.elem).append($tbody);
        if ($config.paging) {
            $('head').append([
                '<style type="text/css">',
                '.royui-treetable tfoot{background:#f9f9f9}',
                '.royui-notallowed{cursor:not-allowed}',
                '.royui-paging{color:#666;display:block;width:auto;height:50px;line-height:50px;text-align:right}',
                '.royui-paging .royui-pagesize{width:60px;height:26px;line-height:26px;border:solid 1px #9daaff;outline:none;background:#fff}',
                '.royui-paging a{border:solid 1px #e1e1e1;color:#3b9acb;text-decoration:none}',
                '.royui-paging a,.royui-paging span{display:inline-block;line-height:26px;margin:0 3px;padding:0 8px}',
                '.royui-paging a:hover{border-color:#06e;background:#09f;color:#fff}',
                '.royui-paging .royui-current{font-size:18px;font-weight:bold}',
                '.royui-paging .royui-jump-to{width:50px;height:26px;line-height:26px;border:solid 1px #e1e1e1;outline:none}',
                '.royui-paging .royui-jump-btn{height:24px;line-height:20px;padding:0 5px;overflow:hidden}',
                '</style>'
            ].join(''));
        let $page = 1, $pagesize = $config.pagesize;
            let $url = location.href; // 取得整个 url
            let $index = $url.indexOf('?'); // 获取所有参数
            let $params = $is_ajax ? {} : '';
            if ($index > 0) {
                let $str = $url.substr($index + 1);
                let $arr = $str.split('&'); // 把各参数放入数组
                for (let $i = 0; $i < $arr.length; $i++) {
                    let $num = $arr[$i].indexOf('=');
                    if ($num > 0) {
                        if ($arr[$i].substr(0, $num) === 'pagesize') {
                            $pagesize = parseInt($arr[$i].substr($num + 1))
                        }
                        if ($arr[$i].substr(0, $num) === 'page') {
                            $page = parseInt($arr[$i].substr($num + 1))
                        } else {
                            if ($is_ajax) {
                                let $sarr = $arr[$i].split('=');
                                $params[$sarr[0]] = decodeURI($sarr[1]);
                                if ($config.sort_field) {
                                    $params['sort_field'] = $config.sort_field;
                                    $params['sort_type'] = $config.sort_type
                                }
                            } else {
                                $params += ('&' + $arr[$i]);
                                if ($config.sort_field) {
                                    $params += '&sort_field=' + $config.sort_field;
                                    $params += '&sort_type=' + $config.sort_type
                                }
                            }
                        }
                    }
                }
                if (!$is_ajax && $params !== '') {
                    $params = $params.substr(1)
                }
            }
            let $pages = Math.ceil($config.count / $pagesize);
            if ($pages > 0) {
                if ($is_ajax) {
                    page_turning($params, $page, $pagesize, 0);
                } else {
                    let $colspan = $config.cols.length + 1;
                    let $tfoot = `<tfoot><tr><td colspan="${$colspan}"><div class="royui-paging">`;
                    if ($config.first_page) {
                        let $first_txt = typeof $config.first_page === 'boolean' ? '首页' : $config.first_page
                        if ($page > 1) {
                            let $params_page = strAddParam(1, $params);
                            $tfoot += '<a href="?' + $params_page + '">' + $first_txt + '</a>'
                        } else {
                            $tfoot += `<span class="royui-notallowed">${$first_txt}</span>`;
                        }
                    }
                    if ($config.prev_page) {
                        let $prev_txt = typeof $config.prev_page === 'boolean' ? '上一页' : $config.prev_page
                        if ($page > 1) {
                            let $params_page = strAddParam($page - 1, $params);
                            $tfoot += `<a href="?${$params_page}">${$prev_txt}</a>`;
                        } else {
                            $tfoot += `<span class="royui-notallowed">${$prev_txt}</span>`;
                        }
                    }
                    let $show_pages = $config.show_pages;
                    let $floor = Math.floor($show_pages / 2);
                    let $start = $page > $floor ? $page - $floor : 1,
                        $end = $page < $pages - $floor ? $page + $floor : $pages;
                    if ($page > $floor && $show_pages % 2 === 0) {
                        $start += 1;
                    }
                    if ($start > $pages - $show_pages && $pages > $show_pages) {
                        $start = $pages - $show_pages + 1;
                    }
                    if ($end < $show_pages) {
                        if ($show_pages < $pages) {
                            $end = $show_pages;
                        } else {
                            $end = $pages;
                        }
                    }
                    for (let $j = $start; $j <= $end; $j++) {
                        if ($j === $page) {
                            $tfoot += `<span class="royui-current">${$page}</span>`
                        } else {
                            let $params_page = strAddParam($j, $params);
                            $tfoot += `<a href="?${$params_page}">${$j}</a>`
                        }
                    }
                    if ($config.next_page) {
                        let $next_txt = typeof $config.next_page === 'boolean' ? '下一页' : $config.next_page
                        if ($page < $pages) {
                            let $params_page = strAddParam($page + 1, $params);
                            $tfoot += `<a href="?${$params_page}">${$next_txt}</a>`;
                        } else {
                            $tfoot += `<span class="royui-notallowed">${$next_txt}</span>`;
                        }
                    }
                    if ($config.last_page) {
                        let $last_txt = typeof $config.last_page === 'boolean' ? '尾页' : $config.last_page
                        if ($page < $pages) {
                            let $params_page = strAddParam($pages, $params);
                            $tfoot += `<a href="?${$params_page}">${$last_txt}</a>`
                        } else {
                            $tfoot += `<span class="royui-notallowed">${$last_txt}</span>`;
                        }
                    }
                    if ($config.is_size && $config.size_arr.length > 0) {
                        let $pagesize_str = '<span><select class="royui-pagesize">', $selected = '';
                        for (let i in $config.size_arr) {
                            if ($pagesize === parseInt($config.size_arr[i])) {
                                $selected = ' selected="1"'
                            } else {
                                $selected = ''
                            }
                            $pagesize_str += `<option value="${$config.size_arr[i]}"${$selected}>${$config.size_arr[i]}</option>`;
                        }
                        $pagesize_str += '</select></span>';
                        $tfoot += $pagesize_str;
                    }
                    if ($config.show_count) {
                        $tfoot += ` &nbsp; 共 <span class="royui-current">${$config.count}</span> 条`;
                    }
                    if ($config.jump_to) {
                        $tfoot += ' &nbsp; <span><input type="text" class="royui-jump-to"></span><span><input type="button" class="royui-jump-btn" value="跳转"></span>';
                    }
                    $tfoot += '</div></td></tr></tfoot>';
                    $(this.elem).append($tfoot);
                    $(this.elem).on('change', '.royui-pagesize', function() {
                        let $ps = $(this).val();
                        let $url = setParam({
                            'pagesize': $ps,
                            'page': 1
                        });
                        window.location.href = $url
                    }).on('click', '.royui-jump-btn', function() {
                        let $to = parseInt($('.royui-jump-to').val());
                        if ($to <= $pages) {
                            let $params_page = strAddParam($to, $params);
                            window.location.href = '?' + $params_page;
                        } else {
                            layer.msg('超过总页数');
                        }
                    }).on('keydown', '.royui-jump-to', function(e) {
                        if (e.keyCode === 13) {
                            $('.royui-jump-btn').click()
                        }
                    });
                }
            }
        }
    }
};
//设置url中参数值
let setParam = function(param, value = '') {
    let query = location.search.substring(1);
    console.log(query)
    let type = typeof param;
    if (type === 'string') {
        let p = new RegExp("(^|)" + param + "=([^&]*)(|$)");
        if (p.test(query)) {
            //query = query.replace(p,"$1="+value);
            let firstParam = query.split(param)[0];
            let secondParam = query.split(param)[1];
            if (secondParam.indexOf("&") > -1) {
                let lastParam = secondParam.split("&")[1];
                return `?${firstParam}&${param}=${value}&${lastParam}`;
            } else {
                if (firstParam) {
                    return `?${firstParam}${param}=${value}`;
                } else {
                    return `?${param}=${value}`;
                }
            }
        } else {
            if (query == '') {
                return `?${param}=${value}`;
            } else {
                return `?${query}&${param}=${value}`;
            }
        }
    } else if (type === 'object') {
        let $paramList = {};
        if (query !== '') {
            let paramArr = query.split('&');
            for (let j = 0; j < paramArr.length; j++) {
                let $sarr = paramArr[j].split('=');
                $paramList[$sarr[0]] = $sarr[1]
            }
        }
        for (let key in param) {
            $paramList[key] = param[key];
        }
        console.log($paramList)
        let str = objToStr($paramList);
        return `?${str}`
    }
}
// 获取URL中各参数
let getUrlParam = function ($url) {
    if ($url === undefined || $url === null || $url === '') {
        return []
    }
    let $str = $url;
    if ($url.substr(0, 1) === '?') {
        $str = $url.substr(1);
    }
    let $param = $str.split('&'), $params = [];
    $($param).each(function (i, v) {
        let arr = v.split('=');
        $params[arr[0]] = arr[1]
    });
    return $params
}
// 数组按字母排序
let keySort = function($arr) {
    if ($arr === null || $arr === undefined) {
        return '';
    }
    let $keys = Object.keys($arr).sort();
    let $newArr = {};
    for (let i = 0; i < $keys.length; i++) {
        $newArr[$keys[i]] = $arr[$keys[i]];
    }
    return $newArr;
};
// 字符串参数添加分页参数
let strAddParam = function($page, $param = '') {
    if ($param === '') {
        return `page=${$page}`
    }
    return $param + `&page=${$page}`
};
// 对象转为url参数串
let objToStr = function(obj) {
    let $str = '';
    for (let p in obj) {
        $str += (`&${p}=${obj[p]}`);
    }
    if ($str !== '') {
        $str = $str.substr(1);
    }
    return $str;
};
// 翻页方法
let page_turning = function($page_param, $page = 1, $pagesize = 20, $need_load = 1) {
    $page_param['page'] = $page;
    $page_param['pagesize'] = $pagesize;
    if ($need_load) {
        let $loading = '<span class="royui-loading-big"></span>';
        $('body').append($loading);
        $.ajax({
            type: $config.method,
            dataType: 'json',
            cache: false,
            url: $config.url,
            data: $page_param,
            success: function($data) {
                $data = $data.data;
                $($prop).find('tbody').remove();
                let $tbody = '<tbody>';
                $($data).each(function($i, $item) {
                    $tbody += '<tr>';
                    if ($config.checkbox) {
                        let strItem = JSON.stringify($item)
                        $tbody += `<td style="text-align:center"><span class="royui-checkbox" onclick='checkItem(this,${strItem})'><input type="checkbox" class="royui_checkbox royui-hid" value="${$item[$config.tree.primary_key]}" /><span class="royui-checkbox-inner"></span></span></td>`;
                        if (typeof $config.onSelected === 'function') {
                            $($prop).on('click', '.royui-checkbox', function() {
                                if (parseInt($item[$config.tree.primary_key]) === parseInt($(this).find('input:checkbox').val())) {
                                    $config.onSelected($item, this);
                                }
                            });
                        }
                    } else {
                        $tbody += '<td style="width:15px"></td>'
                    }
                    $($config.cols).each(function($ii, $col) {
                        let $icon = '', $tip = false, $hh = $item.has_children ?? false;
                        if ($ii === $config.tree.iconIndex) {
                            $tip = true;
                            if ($hh) {
                                $icon = $config.tree.icon;
                            }
                        }
                        $tbody += createCol($col, 0, $item, $icon, $config.tree.primary_key, 0, $tip);
                    });
                    $tbody += '</tr>';
                });
                $tbody += '</tbody>';
                $($prop).append($tbody);
                $('.royui-loading-big').remove();
            },
            error: function($err) {
                console.log($err)
            }
        });
    }
    $page_param = JSON.stringify($page_param);
    $($prop).find('tfoot').remove();
    let $tfoot = `<tfoot><tr><td colspan="${$config.cols.length+1}"><div class="royui-paging">`;
    if ($config.first_page) {
        let $first_txt = typeof $config.first_page === 'boolean' ? '首页' : $config.first_page
        if ($page > 1) {
            $tfoot += `<a href="javascript:" onclick='page_turning(${$page_param},1,${$pagesize})'>${$first_txt}</a>`
        } else {
            $tfoot += `<span class="royui-notallowed">${$first_txt}</span>`;
        }
    }
    if ($config.prev_page) {
        let $prev_txt = typeof $config.prev_page === 'boolean' ? '上一页' : $config.prev_page
        if ($page > 1) {
            $tfoot += `<a href="javascript:" onclick='page_turning(${$page_param},${$page-1},${$pagesize})'>${$prev_txt}</a>`;
        } else {
            $tfoot += `<span class="royui-notallowed">${$prev_txt}</span>`;
        }
    }
    let $pages = Math.ceil($config.count / $pagesize), $show_pages = $config.show_pages;
    let $floor = Math.floor($show_pages / 2);
    let $start = $page > $floor ? $page - $floor : 1, $end = $page < $pages - $floor ? $page + $floor : $pages;
    if ($page > $floor && $show_pages % 2 === 0) {
        $start += 1;
    }
    if ($start > $pages - $show_pages && $pages > $show_pages) {
        $start = $pages - $show_pages + 1;
    }
    if ($end < $show_pages) {
        if ($show_pages < $pages) {
            $end = $show_pages;
        } else {
            $end = $pages;
        }
    }
    for (let $n = $start; $n <= $end; $n++) {
        if ($n != $page) {
            $tfoot += `<a href="javascript:" onclick='page_turning(${$page_param},${$n},${$pagesize})'>${$n}</a>`;
        } else {
            $tfoot += `<span class="royui-current">${$n}</span>`;
        }
    }
    if ($config.next_page) {
        let $next_txt = typeof $config.next_page === 'boolean' ? '下一页' : $config.next_page
        if ($page < $pages) {
            $tfoot += `<a href="javascript:" onclick='page_turning(${$page_param},${$page+1},${$pagesize})'>${$next_txt}</a>`;
        } else {
            $tfoot += `<span class="royui-notallowed">${$next_txt}</span>`;
        }
    }
    if ($config.last_page) {
        let $last_txt = typeof $config.last_page === 'boolean' ? '尾页' : $config.last_page
        if ($page < $pages) {
            $tfoot += `<a href="javascript:" onclick='page_turning(${$page_param},${$pages},${$pagesize})'>${$last_txt}</a>`
        } else {
            $tfoot += `<span class="royui-notallowed">${$last_txt}</span>`;
        }
    }
    if ($config.is_size && $config.size_arr.length > 0) {
        let $pagesize_str = '<span><select class="royui-pagesize">', $selected = '';
        for (let i in $config.size_arr) {
            if (parseInt($pagesize) === $config.size_arr[i]) {
                $selected = ' selected="1"'
            } else {
                $selected = ''
            }
            $pagesize_str += `<option value="${$config.size_arr[i]}"${$selected}>${$config.size_arr[i]}</option>`;
        }
        $pagesize_str += '</select></span>';
        $tfoot += $pagesize_str;
    }
    if ($config.show_count) {
        $tfoot += ` &nbsp; 共 <span class="royui-current">${$config.count}</span> 条`;
    }
    if ($config.jump_to) {
        $tfoot += ' &nbsp; <span><input type="text" class="royui-jump-to"></span><span><input type="button" class="royui-jump-btn" value="跳转"></span>';
    }
    $tfoot += '</div></td></tr></tfoot>';
    $($prop).append($tfoot);
    $($prop).off('click').on('click', '.royui-jump-btn', function() {
        let $to = parseInt($('.royui-jump-to').val());
        if ($to <= $pages) {
            page_turning(JSON.parse($page_param), $to, $pagesize)
        } else {
            layer.msg('超过总页数');
        }
    });
    $($prop).off('keydown').on('keydown', '.royui-jump-to', function(e) {
        if (e.keyCode === 13) {
            $('.royui-jump-btn').click()
        }
    });
    $($prop).off('change').on('change', '.royui-pagesize', function(e) {
        let $ps = $(this).val();
        page_turning(JSON.parse($page_param), 1, $ps, 1)
    })
};
let createCol = function($col, $level, $v, $icon, $key_name, $indent = 0, $tip = false) {
    let $type = $col.type ?? 'normal',
        $class = $col.className ? ` class="${$col.className}"` : '',
        $style = $col.style ? ` style="${$col.style}` : '',
        $data = $col.data ? ` data-${$col.data}="${$col.data_value ?? $v[$col.field]}"` : '';
    let $onclick = '',
        $onmouseover = '',
        $onmouseleave = '',
        $data_id = '',
        $data_tip = '';
    if ($icon !== '') {
        $onclick = ` onclick="clickTD(this,'${$key_name}',${$level+1})"`;
        $data_id = ` data-${$key_name}="${$v[$key_name]}"`;
        $style = $style ? $style + ';cursor:pointer;color:#3a6be0' : ' style="cursor:pointer;color:#3a6be0';
    } else if ($config.checkbox) {
        $onclick = ` onclick="clickCheck(this)"`;
    }
    if ($data_id === '' && $col.data_id) {
        $data_id = ` data-${$key_name}="${$v[$key_name]}"`;
    }
    if ($v['tip'] && $tip) {
        $data_tip = ` data-tip="${$v['tip']}"`;
        $onmouseover = ' onmouseover="mouseOver(this)"';
        $onmouseleave = ' onmouseleave="mouseLeave(this)"';
    }
    if ($level > 0 && $indent === 1) {
        $indent = `text-indent:${$level*6}px;`;
        $style = $style ? `${$style};${$indent}` : ` style="${$indent}`;
    }
    if ($style !== '') {
        $style += '"';
    }
    let $str = `<td${$data_id}${$class}${$style}${$onclick}${$data}>`;
    if ($col.action) {
        let $str_new = '';
        if (typeof $col.template === 'function') {
            $str_new = $col.template($v);
        }
        if ($col.site === 'front') {
            $str += $str_new + ' &nbsp; ';
        }
        $($col.action).each(function($j, $acts) {
            let $act = $acts.matter,
                $url = $acts.url,
                $method = $acts.method,
                $hide = $acts['hide'] ?? '',
                $flag = true;
            if ($hide.field !== undefined && $hide.field_value !== undefined) {
                let $value = $hide.field_value;
                if ($value.indexOf($v[$hide.field]) > -1) {
                    $flag = false
                }
            } else if ($hide === true || $hide === 1) {
                $flag = false
            }
            if ($flag) {
                let $data_url = '',
                    $data_key = '',
                    $data_area = '',
                    $onclicka = '';
                if ($url.indexOf('?') < 0) {
                    $url += `?${$key_name}=${$v[$key_name]}`;
                } else {
                    $url += `&${$key_name}=${$v[$key_name]}`;
                }
                if ($method && $method === 'popup') {
                    $data_url = ` data-url="${$url}"`;
                    $data_key = ` data-${$key_name}="${$v[$key_name]}"`;
                    $data_area = ` data-area="${$acts['area']??['560px','750px']}"`;
                    let $title = '';
                    if ($act === 'edit' || $act === 'modify') {
                        $title = '编辑';
                    } else if ($act === 'info' || $act === 'details') {
                        $title = '详情';
                    } else if ($act === 'delete' || $act === 'del') {
                        $title = '删除';
                    }
                    $onclicka = ` onclick='clickA(this,"${$key_name}","${$title}")'`;
                    $url = 'javascript:';
                }
                if ($act === 'edit' || $act === 'modify') {
                    $str += `<a href="${$url}"${$data_url}${$data_key}${$data_area}${$onclicka} class="royui-button-a">编辑</a> &nbsp; `;
                } else if ($act === 'delete' || $act === 'del') {
                    $data_url = ` data-url="${$acts.url}"`;
                    $data_key = ` data-${$key_name}="${$v[$key_name]}"`;
                    $onclicka = ` onclick="clickA(this,'${$key_name}','删除')"`;
                    $str += `<a href="javascript:" ${$data_url}${$data_key}${$onclicka} class="royui-button-a">删除</a> &nbsp; `;
                } else if ($act === 'info' || $act === 'details') {
                    $str += `<a href="${$url}"${$data_url}${$data_key}${$data_area}${$onclicka} class="royui-button-a">详情</a> &nbsp; `
                }
            }
        })
        if ($col.site === 'after') {
            $str += $str_new;
        }
    } else if (typeof $col.template === "function") {
        $str += `<span${$data_tip}${$onmouseover}${$onmouseleave}>${$icon}${$col.template($v)}</span>`;
    } else if ($type === 'text') {
        $str += `<input type="text" value="${$v[$col.field]??''}" />`;
    } else if ($type === 'select') {
        $str += `<select${$class}${$style}>`;
        $($v[$col.field]).each(function($i, $o) {
            $check = '';
            if ($o.is_checked && $o.is_checked === 1) {
                $check = ' selected="1"';
            }
            $str += `<option value="${$o.value}"${$check}>${$o.name}</option>`;
        });
        $str += '</select>';
    } else if ($type === 'checkbox') {
        $str += `<input type="checkbox" value="${$v[$col.field]??''}" />`;
    } else if ($type === 'normal') {
        if ($col.field.indexOf('.') > 0) {
            let $fields = $col.field.split('.');
            if (isJson($v[$fields[0]])) {
                let $json_v = JSON.parse($v[$fields[0]]);
                $str += '';
                if ($json_v != null) {
                    if ($fields[2]) {
                        $str += $json_v[$fields[1]][$fields[2]] ?? '';
                    } else {
                        $str += $json_v[$fields[1]] ?? ''
                    }
                }
            } else {
                $str += ''
            }
        } else {
            $str += `<span${$data_tip}${$onmouseover}${$onmouseleave}>${$icon}${$v[$col.field]??''}</span>`;
        }
    }
    $str += '</td>';
    return $str;
};
let isJson = function($str) {
    try {
        let $obj = JSON.parse($str);
        if (typeof $obj == 'object' && $obj) {
            return $obj
        } else {
            return false
        }
    } catch (e) {
        console.log(e.message)
        return false
    }
};
let checkAll = function($obj) {
    if ($($obj).hasClass('is-checked') && !$($obj).find('span').hasClass('royui-checkbox-inner-all')) {
        $($obj).removeClass('is-checked');
        $($obj).find('.royui_checkbox_all').prop('checked', false);
        $('.royui_checkbox').prop('checked', false);
        $('.royui-checkbox').removeClass('is-checked')
    } else {
        $($obj).addClass('is-checked').find('span').removeClass('royui-checkbox-inner-all').addClass('royui-checkbox-inner');
        $($obj).find('.royui_checkbox_all').prop('checked', true);
        $('.royui_checkbox').prop('checked', true);
        $('.royui-checkbox').addClass('is-checked')
    }
    if (typeof $config.onSelectAll === 'function') {
        $config.onSelectAll($($obj).find('.royui_checkbox_all'));
    }
};
let checkItem = function($obj, $objItem = null) {
    if ($($obj).hasClass('is-checked')) {
        $($obj).removeClass('is-checked');
        $($obj).find('.royui_checkbox').prop('checked', false);
        let $zong = $($prop).find('td>.royui-checkbox').length;
        let $xz = $($prop).find('td>.is-checked').length;
        if ($xz > 0) {
            if ($xz !== $zong) {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner').addClass('royui-checkbox-inner-all');
            } else {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner-all').addClass('royui-checkbox-inner');
            }
        } else {
            $($prop).find('th>.royui-checkbox').removeClass('is-checked')
        }
    } else {
        $($obj).addClass('is-checked');
        $($obj).find('.royui_checkbox').prop('checked', true);
        let $zong = $($prop).find('td>.royui-checkbox').length;
        let $xz = $($prop).find('td>.is-checked').length;
        if ($xz > 0) {
            if ($xz !== $zong) {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner').addClass('royui-checkbox-inner-all');
            } else {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner-all').addClass('royui-checkbox-inner');
            }
        } else {
            $($prop).find('th>.royui-checkbox').removeClass('is-checked')
        }
    }
    if ($config.checkbox) {
        if (typeof $config.onSelected === 'function') {
            $config.onSelected($objItem, $($obj).find('.royui_checkbox'));
        }
    }
};
let clickTH = function($obj, $field) {
    let $sort = $($obj).find('.sort');
    let $type = '';
    if ($sort.hasClass('royui-icon-triangle-d')) {
        $sort.removeClass('royui-icon-triangle-d').addClass('royui-icon-triangle-u');
        $type = 'asc'
    } else {
        $sort.removeClass('royui-icon-triangle-u').addClass('royui-icon-triangle-d');
        $type = 'desc'
    }
    let $search = location.search;
    let $arr = [];
    if ($search !== '') {
        $search = $search.substr(1);
        $arr = $search.split('&');
        $arr.forEach(($v, $n, $arr) => {
            let $v_a = $v.split('=');
            if ($v_a[0] === 'sort_field' || $v_a[0] === 'sort_type') {
                $arr.splice($n)
            }
        })
    }
    $arr.push('sort_field=' + $field);
    $arr.push('sort_type=' + $type);
    $search = $arr.join('&');
    location.href = '?' + $search;
};
let $clickitems = [];
let clickTD = function($obj, $param_name, $level) {
    let $div = $($obj).find('div'),
        $class = $div.attr('class');
    let $id = $($obj).data($param_name),
        $url = $config.url;
    let $children = $('tr[data-pid="' + $id + '"]');
    if ($class === 'royui-icon-triangle-r') {
        $div.attr('class', 'royui-icon-triangle-d');
        if ($config.is_cache) {
            $children.removeClass('royui-hid');
        }
    } else if ($class === 'royui-icon-triangle-d') {
        $div.attr('class', 'royui-icon-triangle-r');
        removeAll($children);
    }
    if ($children.length > 0) {
        $('tbody>tr').css('background', '#ffffff').hover(function() {
            $(this).css('background', '#f5f5f6')
        }).mouseout(function() {
            $(this).css('background', '#ffffff')
        });
        $('tbody>tr:not(".royui-hid"):even').css('background', '#f9f9f9').hover(function() {
            $(this).css('background', '#f5f5f6')
        }).mouseout(function() {
            $(this).css('background', '#f9f9f9')
        });
        return false;
    }
    let $ls = $config.tree.loading_type === 'line' ? 'royui-loading-line' : 'royui-loading-circle';
    let $loading = `<span class="royui-loading ${$ls}"></span>`;
    $($obj).append($loading);
    let $param = {};
    $param[$param_name] = $id;
    $.ajax({
        type: $config.method,
        dataType: 'json',
        cache: false,
        url: $url,
        data: $param,
        success: function($data) {
            let $str = '';
            if ($data.code === 200 || $data.code === 0 || $data.status === 200 || $data.status === 0) {
                $($data.data).each(function($i, $item) {
                    $str += '<tr data-pid="' + $id + '">';
                    if ($config.checkbox) {
                        $str += `<td style="text-align:center"><span class="royui-checkbox" onclick="checkItem(this)"><input type="checkbox" class="royui_checkbox royui-hid" value="${$item[$config.tree.primary_key]}" /><span class="royui-checkbox-inner"></span></span></td>`;
                    } else {
                        $str += '<td style="width:15px"></td>'
                    }
                    $($config.cols).each(function($ii, $col) {
                        let $icon = '', $hh = $item.has_children ?? false;
                        let $indent = 0;
                        if ($ii === $config.tree.iconIndex) {
                            $indent = 1;
                            if ($hh) {
                                $icon = $config.tree.icon;
                            }
                        }
                        $str += createCol($col, $level + 1, $item, $icon, $config.tree.primary_key, $indent, $indent);
                    });
                    $str += '</tr>';
                    if (typeof $config.onSelected === 'function' && $clickitems.indexOf($item[$config.tree.primary_key]) < 0) {
                        $clickitems.push($item[$config.tree.primary_key]);
                        $($prop).on('click', '.royui-checkbox', function() {
                            if (parseInt($item[$config.tree.primary_key]) === parseInt($(this).find('input:checkbox').val())) {
                                $config.onSelected($item, this);
                            }
                        });
                    }
                });
            }
            $($obj).parent('tr').after($str);
            $('.royui-loading').remove();
        }
    })
};
let clickCheck = function($obj) {
    let $cbx = $($obj).parent('tr').find('.royui_checkbox');
    let $ckb = $($obj).parent('tr').find('.royui-checkbox');
    if ($cbx.is(':checked')) {
        $ckb.click()
        $cbx.prop('checked', false);
        $ckb.removeClass('is-checked');
        let $zong = $($prop).find('td>.royui-checkbox').length;
        let $xz = $($prop).find('td>.is-checked').length;
        if ($xz > 0) {
            if ($xz !== $zong) {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner').addClass('royui-checkbox-inner-all');
            } else {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner-all').addClass('royui-checkbox-inner');
            }
        } else {
            $($prop).find('th>.royui-checkbox').removeClass('is-checked')
        }
    } else {
        $ckb.click()
        $cbx.prop('checked', true);
        $ckb.addClass('is-checked');
        let $zong = $($prop).find('td>.royui-checkbox').length;
        let $xz = $($prop).find('td>.is-checked').length;
        if ($xz > 0) {
            if ($xz !== $zong) {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner').addClass('royui-checkbox-inner-all');
            } else {
                $($prop).find('th>.royui-checkbox').addClass('is-checked').find('span').removeClass('royui-checkbox-inner-all').addClass('royui-checkbox-inner');
            }
        } else {
            $($prop).find('th>.royui-checkbox').removeClass('is-checked')
        }
    }
};
let clickA = function($obj, $param_name, $title) {
    let $id = $($obj).data($param_name), $url = $($obj).data('url');
    let $area = '';
    if ($($obj).data('area') !== undefined) {
        $area = $($obj).data('area').split(',');
    }
    let $param = {};
    $param[$param_name] = $id;
    if ($title === '详情') {
        layer.open({
            type: 2,
            title: $title,
            content: $url,
            area: $area,
            closeBtn: 2,
            btn: ['确定'],
            btn1: function($index) {
                layer.close($index);
            }
        });
    } else if ($title === '编辑') {
        let $open = layer.open({
            type: 2,
            title: $title,
            content: $url,
            area: $area,
            closeBtn: 2,
            btn: ['确定', '取消'],
            yes: function($index, $layero) {
                let $body = $layero.find('iframe').contents().find('body');
                let $param = decodeURIComponent($($body).find('form').serialize());
                $param = $param.split('&');
                let $params = {};
                $($param).each(function($n, $o) {
                    let $key = $o.split('=')[0];
                    if ($key.indexOf('[]') === -1) {
                        $params[$key] = $o.split('=')[1];
                    } else {
                        $key = $key.substring(0, $key.indexOf('[]'));
                        let $count = 0;
                        if ($params[$key] !== undefined) {
                            $count = $params[$key].length;
                        } else {
                            $params[$key] = [];
                        }
                        $params[$key][$count] = $o.split('=')[1];
                    }
                });
                console.log($param, $params)
                $.ajax({
                    type: 'post',
                    dataType: 'json',
                    cache: false,
                    url: $url,
                    data: $params,
                    success: function($data) {
                        if (typeof $config.onUpdated === 'function') {
                            $config.onUpdated($data, $params, $obj);
                        } else {
                            if (($data.code !== undefined && $data.code !== 0 && $data
                                    .code !== 200) || ($data.status !== undefined && $data
                                    .status !== 0 && $data.status !== 200)) {
                                let $msg = $data.message ?? '修改失败'
                                layer.msg($msg, {
                                    icon: 2,
                                    time: 1500
                                })
                                return false
                            } else {
                                let $msg = $data.message ?? '修改成功'
                                layer.msg($msg, {
                                    icon: 1,
                                    time: 1500
                                }, function() {
                                    window.location.reload()
                                })
                            }
                        }
                    }
                })
            },
            btn2: function($index) {
                layer.close($index);
            }
        });
    } else if ($title === '删除') {
        layer.confirm('确实要删除吗？', {
            icon: 3
        }, function() {
            $.ajax({
                type: 'post',
                dataType: 'json',
                cache: false,
                url: $url,
                data: $param,
                success: function($data) {
                    if (typeof $config.onDeleted === 'function') {
                        $config.onDeleted($data, $param, $obj);
                        $('tbody>tr').css('background', '#ffffff').hover(function() {
                            $(this).css('background', '#f5f5f6')
                        }).mouseout(function() {
                            $(this).css('background', '#ffffff')
                        });
                        $('tbody>tr:not(".royui-hid"):even').css('background', '#f9f9f9').hover(
                            function() {
                                $(this).css('background', '#f5f5f6')
                            }).mouseout(function() {
                            $(this).css('background', '#f9f9f9')
                        });
                    } else {
                        if (($data.code !== undefined && $data.code !== 0 && $data.code !==
                            200) || ($data.status !== undefined && $data.status !== 0 && $data
                                .status !== 200)) {
                            console.log($data)
                            let $msg = $data.message ?? '删除失败'
                            layer.msg($msg, {
                                icon: 2,
                                time: 1500
                            })
                            return false
                        } else {
                            let $msg = $data.message ?? '删除成功';
                            layer.msg($msg, {
                                icon: 1,
                                time: 1000
                            }, function() {
                                window.location.reload();
                            })
                        }
                    }
                }
            });
        });
    }
};
let $tip = null;
let mouseOver = function($obj) {
    let $msg = $($obj).data('tip');
    $tip = layer.tips($msg, $($obj), {
        tips: [2, '#b92'],
        time: -1
    });
};
let mouseLeave = function() {
    layer.close($tip);
};
let removeAll = function($list) {
    $($list).each(function($n, $item) {
        let $id = $($item).find('td[data-' + $config.tree.primary_key + ']').data($config.tree.primary_key);
        if ($id) {
            let $children = $('tr[data-pid="' + $id + '"]');
            if ($children) {
                removeAll($children);
            }
            if ($config.is_cache) {
                $children.find('div').removeClass('royui-icon-triangle-d').addClass('royui-icon-triangle-r');
                $children.addClass('royui-hid');
            } else {
                $children.remove();
            }
        }
    });
    if ($config.is_cache) {
        $list.find('div').removeClass('royui-icon-triangle-d').addClass('royui-icon-triangle-r');
        $list.addClass('royui-hid');
    } else {
        $list.remove();
    }
};
Royui.prototype.paging = function($options) {
    let $config = {
        count: $options.count ?? undefined, // 总条数
        page_size: $options.page_size ?? 10, // 每页多少条
        is_size: $options.is_size ?? false, // 是否显示每页大小数组
        size_arr: $options.size_arr ?? [10, 20, 30, 50], // 每页分页大小数组
        first_page: $options.first_page ?? true, // 是否开启首页按钮
        prev_page: $options.prev_page ?? true, // 是否开启上一页按钮
        next_page: $options.next_page ?? true, // 是否开启下一页按钮
        last_page: $options.last_page ?? true, // 是否开启尾页按钮
        show_pages: $options.show_pages ?? 5, // 最多显示页码数
        show_total: $options.show_total ?? true, // 是否显示总条数
        jump_to: $options.jump_to ?? false, // 是否显示跳转到
    };
    $('head').append([
        '<style type="text/css">',
        '.royui-notallowed{cursor:not-allowed}',
        '.royui-paging{background:#f9f9f9;color:#666;display:block;width:auto;height:50px;line-height:50px;text-align:right}',
        '.royui-paging .royui-pagesize{width:60px;height:26px;line-height:26px;border:solid 1px #9daaff;outline:none;background:#fff}',
        '.royui-paging a{border:solid 1px #e1e1e1;color:#3b9acb;text-decoration:none}',
        '.royui-paging a,.royui-paging span{display:inline-block;line-height:26px;margin:0 3px;padding:0 8px}',
        '.royui-paging a:hover{border-color:#06e;background:#09f;color:#fff}',
        '.royui-paging .royui-current{font-size:18px;font-weight:bold}',
        '.royui-paging .royui-jump-to{width:50px;height:26px;line-height:26px;border:solid 1px #e1e1e1;outline:none}',
        '.royui-paging .royui-jump-btn{height:24px;line-height:20px;padding:0 5px;overflow:hidden}',
        '</style>'
    ].join(''));
    let $page = 1, $page_size = $config.page_size;
    let $url = location.href; // 取得整个 url
    let $wen = $url.indexOf('?'); // 获取所有参数
    let $params = '';
    if ($wen > 0) {
        let $str = $url.substr($wen + 1);
        let $arr = $str.split('&'); // 把各参数放入数组
        for (let $i = 0; $i < $arr.length; $i++) {
            let $num = $arr[$i].indexOf('=');
            if ($num > 0) {
                if ($arr[$i].substr(0, $num) === 'page') {
                    $page = parseInt($arr[$i].substr($num + 1))
                } else {
                    $params += '&' + $arr[$i];
                }
                if ($arr[$i].substr(0, $num) === 'pagesize') {
                    $page_size = parseInt($arr[$i].substr($num + 1))
                }
            }
        }
    }
    let $str = '', $show_pages = $config.show_pages;
    let $floor = Math.floor($show_pages / 2), $pages = Math.ceil($config.count / $page_size);
    let $start = $page > $floor ? $page - $floor : 1, $end = $page < $pages - $floor ? $page + $floor : $pages;
    if ($page > $floor && $show_pages % 2 === 0) {
        $start += 1;
    }
    if ($start > $pages - $show_pages && $pages > $show_pages) {
        $start = $pages - $show_pages + 1;
    }
    if ($end < $show_pages) {
        if ($show_pages < $pages) {
            $end = $show_pages;
        } else {
            $end = $pages;
        }
    }
    if ($config.show_total) {
        $str += '<span>共 ' + $config.count + ' 条</span>';
    }
    if ($config.first_page) {
        let $first_txt = typeof $config.first_page === 'boolean' ? '首页' : $config.first_page;
        if ($page > 1) {
            $str += `<a href="?page=1${$params}">${$first_txt}</a>`;
        } else {
            $str += `<span class="royui-notallowed">${$first_txt}</span>`;
        }
    }
    if ($config.prev_page) {
        let $prev_txt = typeof $config.prev_page === 'boolean' ? '上一页' : $config.prev_page;
        if ($page > 1) {
            $str += `<a href="?page=${$page-1}${$params}">${$prev_txt}</a>`;
        } else {
            $str += `<span class="royui-notallowed">${$prev_txt}</span>`
        }
    }
    for (let $i = $start; $i <= $end; $i++) {
        if ($i === $page) {
            $str += `<span class="royui-current">${$i}</span>`;
        } else {
            $str += `<a href="?page=${$i}${$params}">${$i}</a>`;
        }
    }
    if ($config.next_page) {
        let $next_txt = typeof $config.next_page === 'boolean' ? '下一页' : $config.next_page;
        if ($page < $pages) {
            $str += `<a href="?page=${$page+1}${$params}">${$next_txt}</a>`;
        } else {
            $str += `<span class="royui-notallowed">${$next_txt}</span>`;
        }
    }
    if ($config.last_page) {
        let $last_txt = typeof $config.last_page === 'boolean' ? '尾页' : $config.last_page;
        if ($page < $pages) {
            $str += `<a href="?page=${$pages}${$params}">${$last_txt}</a>`;
        } else {
            $str += `<span class="royui-notallowed">${$last_txt}</span>`;
        }
    }
    if ($config.is_size) {
        $str += '<span><select class="royui-pagesize">';
        for (let i in $config.size_arr) {
            if ($page_size === parseInt($config.size_arr[i])) {
                $selected = ' selected="1"'
            } else {
                $selected = ''
            }
            $str += `<option value="${$config.size_arr[i]}"${$selected}>${$config.size_arr[i]}</option>`
        }
        $str += '</select></span>'
    }
    if ($config.jump_to) {
        $str += '<span><input type="text" class="royui-jump-to"></span><span><input type="button" class="royui-jump-btn" value="跳转"></span>'
    }
    $($prop).addClass('royui-paging').append($str);
    $($prop).on('change', '.royui-pagesize', function() {
        $ps = $(this).val();
        let $url = setParam({
            'page': 1,
            'pagesize': $ps
        });
        window.location.href = $url
    }).on('click', '.royui-jump-btn', function() {
        let $to = parseInt($('.royui-jump-to').val());
        if ($to <= $pages) {
            window.location.href = '?page=' + $to + $params;
        }
    }).on('keydown', '.royui-jump-to', function(e) {
        if (e.keyCode === 13) {
            $('.royui-jump-btn').click()
        }
    })
};
Royui.prototype.watermark = function($options) {
    let $mask_div = document.querySelectorAll('.mask_div');
    if ($mask_div.length > 0) {
        for (let i = 0; i < $mask_div.length; i++) {
            $mask_div[i].remove()
        }
    }
    let $date = new Date();
    let $year = $date.getFullYear(),
        $m = $date.getMonth() + 1,
        $d = $date.getDate(),
        $h = $date.getHours(),
        $i = $date.getMinutes(),
        $s = $date.getSeconds();
    if ($m < 10) {
        $m = '0' + $m
    }
    if ($d < 10) {
        $d = '0' + $d
    }
    if ($h < 10) {
        $h = '0' + $h
    }
    if ($i < 10) {
        $i = '0' + $i
    }
    if ($s < 10) {
        $s = '0' + $s
    }
    let $watermark_txt = $year + '-' + $m + '-' + $d + ' ' + $h + ':' + $i + ':' + $s;
    let $watermark_config = {
        watermark_txt: $options.watermark_txt ?? $watermark_txt, // 水印文字
        watermark_x: $options.watermark_x ?? 20, // 水印起始位置x轴坐标
        watermark_y: $options.watermark_y ?? 20, // 水印起始位置Y轴坐标
        watermark_rows: $options.watermark_rows ?? 0, // 水印行数
        watermark_cols: $options.watermark_cols ?? 0, // 水印列数
        watermark_x_space: $options.watermark_x_space ?? 100, // 水印x轴间隔
        watermark_y_space: $options.watermark_y_space ?? 50, // 水印y轴间隔
        watermark_color: $options.watermark_color ?? '#aaaaaa', // 水印字体颜色
        watermark_alpha: $options.watermark_alpha ?? 0.3, // 水印透明度
        watermark_fontsize: $options.watermark_fontsize ?? '16px', // 水印字体大小
        watermark_font: $options.watermark_font ?? '微软雅黑', // 水印字体样式
        watermark_width: $options.watermark_width ?? 210, // 水印宽度
        watermark_height: $options.watermark_height ?? 80, // 水印长(高)度
        watermark_angle: $options.watermark_angle ?? 15, // 水印倾斜度数
    };
    let $body_height = Math.max(document.documentElement.clientHeight, document.body.clientHeight);
    document.body.style.minHeight = $body_height + 'px';
    // 采用配置项替换默认值，作用类似jquery.extend
    if (arguments.length === 1 && typeof arguments[0] === 'object') {
        let $src = arguments[0] || {};
        for (let $k in $src) {
            if ($src[$k] && $watermark_config[$k] && $src[$k] === $watermark_config[$k]) {
                continue;
            } else if ($src[$k]) {
                $watermark_config[$k] = $src[$k];
            }
        }
    }
    let $oTemp = document.createDocumentFragment();
    // 获取页面最大宽度
    let $page_width = Math.max(document.body.scrollWidth, document.body.clientWidth);
    $page_width = $page_width * 0.985;
    // 获取页面最大高度
    let $page_height = Math.max(document.body.scrollHeight, document.body.clientHeight);
    // 如果将水印列数设置为0，或水印列数设置过大，超过页面最大宽度，则重新计算水印列数和水印x轴间隔
    let $cols = $watermark_config.watermark_cols,
        $width = $watermark_config.watermark_width,
        $x = $watermark_config.watermark_x,
        $x_space = $watermark_config.watermark_x_space;
    if ($cols === 0 || parseInt($x + $width * $cols + $x_space * ($cols - 1)) > $page_width) {
        $cols = parseInt(($page_width - $x + $x_space) / ($width + $x_space));
        $watermark_config.watermark_x_space = parseInt(($page_width - $x - $width * $cols) / ($cols - 1));
    }
    // 如果将水印行数设置为0，或水印行数设置过大，超过页面最大长度，则重新计算水印行数和水印y轴间隔
    let $rows = $watermark_config.watermark_rows,
        $y = $watermark_config.watermark_y,
        $height = $watermark_config.watermark_height,
        $y_space = $watermark_config.watermark_y_space;
    if ($rows === 0 || parseInt($y + $height * $rows + $y_space * ($rows - 1)) > $page_height) {
        $rows = parseInt(($y_space + $page_height - $y) / ($height + $y_space));
        $watermark_config.watermark_y_space = parseInt(($page_height - $y - $height * $rows) / ($rows - 1));
    }
    let $x2, $y2;
    for (let $i = 0; $i < $rows; $i++) {
        $y2 = $y + ($height + $y_space) * $i;
        for (let $j = 0; $j < $cols; $j++) {
            $x2 = $x + ($width + $x_space) * $j;
            let $mask_div = document.createElement('div');
            $mask_div.id = 'mask_div' + $i + $j;
            $mask_div.className = 'mask_div';
            // 设置水印div文字
            $mask_div.appendChild(document.createTextNode($watermark_config.watermark_txt));
            // 设置水印div倾斜显示
            $mask_div.style.webkitTransform = `rotate(-${$watermark_config.watermark_angle}deg)`;
            $mask_div.style.MozTransform = `rotate(-${$watermark_config.watermark_angle}deg)`;
            $mask_div.style.msTransform = `rotate(-${$watermark_config.watermark_angle}deg)`;
            $mask_div.style.OTransform = `rotate(-${$watermark_config.watermark_angle}deg)`;
            $mask_div.style.transform = `rotate(-${$watermark_config.watermark_angle}deg)`;
            $mask_div.style.visibility = '';
            $mask_div.style.position = 'absolute';
            $mask_div.style.left = $x2 + 'px';
            $mask_div.style.top = $y2 + 'px';
            $mask_div.style.overflow = 'hidden';
            $mask_div.style.zIndex = '9999';
            $mask_div.style.pointerEvents = 'none'; // pointer-events:none  让水印不遮挡页面的点击事件
            // $mask_div.style.border="solid #eee 1px";
            $mask_div.style.opacity = $watermark_config.watermark_alpha;
            $mask_div.style.fontFamily = $watermark_config.watermark_font;
            $mask_div.style.fontSize = $watermark_config.watermark_fontsize;
            $mask_div.style.color = $watermark_config.watermark_color;
            $mask_div.style.textAlign = 'center';
            $mask_div.style.width = $watermark_config.watermark_width + 'px';
            $mask_div.style.height = $watermark_config.watermark_height + 'px';
            $mask_div.style.display = 'block';
            $mask_div.style.whiteSpace = 'break-spaces';
            $oTemp.appendChild($mask_div);
        }
    }
    document.body.appendChild($oTemp);
    window.onresize = function() {
        royui().watermark($options)
    }
};
Royui.prototype.timequantum = function() {
    $('head').append([
        '<style type="text/css">',
        '.time_quantum_table{margin:35px 0px 25px 50px;border:1px solid #9F9F9F;border-spacing:0;border-collapse:collapse}',
        '.time_quantum_table .time_quantum_num{height:24px}',
        '.time_quantum_table th,.time_quantum_table td{text-align:center;border:1px solid #9F9F9F;border-collapse:collapse}',
        '.time_quantum_grain{width:15px;height:30px;background-color:rgba(252, 255, 242, 0.93)}',
        '.time_quantum_grain_blue{background-color:#d66ed3}',
        '.time_selected_contents{font-size:12px;color:#9F9F9F}',
        '.time_quantum_table .time_quantum_title{display:inline-block;float:left;margin:15px}',
        '.time_quantum_table .time_quantum_clean_btn{color:#45ceff;display:inline-table;float:right;margin:15px;cursor:pointer}',
        '.time_selected_contents .time_quantum_selected{text-align:left;margin:15px;display:none}',
        '.time_selected_contents .time_quantum_selected div{margin:10px 0px;display:none}',
        '.time_selected_contents .time_quantum_selected div span{display:inline-table;margin:0px 5px}',
        '.time_selected_contents .time_quantum_selected .time_quantum_value{color:#1b1b1f}',
        '</style>'
    ].join(''))
    $(this.elem).attr('onselectstart', 'return false');
    var $str = '<table class="time_quantum_table">' +
        '<tr>' +
        '<th rowspan="2" width="120">星期/时间</th>' +
        '<th colspan="24" height="24">00:00 - 12:00</th>' +
        '<th colspan="24">12:00 - 24:00</th>' +
        '</tr>' +
        '<tr class="time_tr_header"></tr>' +
        '<tr class="time_quantum" data-week="1" title="星期一">' +
        '<td>星期一</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="2" title="星期二">' +
        '<td>星期二</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="3" title="星期三">' +
        '<td>星期三</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="4" title="星期四">' +
        '<td>星期四</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="5" title="星期五">' +
        '<td>星期五</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="6" title="星期六">' +
        '<td>星期六</td>' +
        '</tr>' +
        '<tr class="time_quantum" data-week="7" title="星期天">' +
        '<td>星期天</td>' +
        '</tr>' +
        '<tbody>' +
        '<tr>' +
        '<td colspan="49" class="time_selected_contents">' +
        '<span class="time_quantum_title">可拖动鼠标选择时间段</span>' +
        '<span class="time_quantum_clean_btn">清空选择</span>' +
        '<div style="clear: both"></div>' +
        '<div class="time_quantum_selected">' +
        '<div class="quantum_selected_1">' +
        '<span>星期一：</span>' +
        '<span id="quantum_selected_times_1" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_2">' +
        '<span>星期二：</span>' +
        '<span id="quantum_selected_times_2" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_3">' +
        '<span>星期三：</span>' +
        '<span id="quantum_selected_times_3" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_4">' +
        '<span>星期四：</span>' +
        '<span id="quantum_selected_times_4" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_5">' +
        '<span>星期五：</span>' +
        '<span id="quantum_selected_times_5" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_6">' +
        '<span>星期六：</span>' +
        '<span id="quantum_selected_times_6" class="qst"></span>' +
        '</div>' +
        '<div class="quantum_selected_7">' +
        '<span>星期天：</span>' +
        '<span id="quantum_selected_times_7" class="qst"></span>' +
        '</div>' +
        '</div>' +
        '</td>' +
        '</tr>' +
        '</tbody>' +
        '</table>';
    $(this.elem).html($str);
    let timeTrHeaderHtml = '';
    let timeTdHtml = '';
    for (let i = 0; i < 24; i++) {
        timeTrHeaderHtml += `<td colspan="2" class="time_quantum_num">${i}</td>`;
    }
    for (let i = 0; i < 48; i++) {
        timeTdHtml += `<td class="time_quantum_grain" data-time-num="${i}"></td>`
    }
    $('.time_tr_header').html(timeTrHeaderHtml);
    $('.time_quantum').append(timeTdHtml);
    var timequantumClick = false;
    var timequentumClickX = 0;
    var timequentumClickY = 0;
    var timequentumMouseType = 0;
    var timequentumStartElement = false;
    $('.time_quantum_grain').mousedown(function() {
        timequantumClick = true;
        timequentumClickX = $(this).offset().left;
        timequentumClickY = $(this).offset().top;
        let selectedStatus = $(this).data('selected-status');
        if (selectedStatus == 1) {
            timequentumMouseType = 1;
        } else {
            timequentumMouseType = 0;
        }
        timequentumStartElement = $(this);
    }).mousemove(function(e) {
        if (timequantumClick) {
            let mouseX = e.pageX;
            let mouseY = e.pageY;
            $.each($('.time_quantum_grain'), function() {
                let itemX = $(this).offset().left;
                let itemY = $(this).offset().top;
                let selectedTempStatus = $(this).data('selected-temp-status');
                if (mouseX < timequentumClickX && mouseY < timequentumClickY) {
                    //第一象限
                    if (itemX >= mouseX && itemX <= timequentumClickX && itemY >= mouseY && itemY <= timequentumClickY) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 1);
                    } else if (selectedTempStatus == 1) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 0);
                    }
                } else if (mouseX > timequentumClickX && mouseY < timequentumClickY) {
                    //第二象限
                    if (itemX <= mouseX && itemX >= timequentumClickX && itemY >= mouseY && itemY <= timequentumClickY) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 1);
                    } else if (selectedTempStatus == 1) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 0);
                    }
                } else if (mouseX < timequentumClickX && mouseY > timequentumClickY) {
                    //第三象限
                    if (itemX >= mouseX && itemX <= timequentumClickX && itemY <= mouseY && itemY >= timequentumClickY) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 1);
                    } else if (selectedTempStatus == 1) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 0);
                    }
                } else if (mouseX > timequentumClickX && mouseY > timequentumClickY) {
                    //第四象限
                    if (itemX <= mouseX && itemX >= timequentumClickX && itemY <= mouseY && itemY >= timequentumClickY) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 1);
                    } else if (selectedTempStatus == 1) {
                        if (timequentumMouseType == 1) {
                            $(this).data('selected-status', 0)
                            $(this).removeClass('time_quantum_grain_blue');
                        } else {
                            $(this).data('selected-status', 1)
                            $(this).addClass('time_quantum_grain_blue')
                        }
                        $(this).data('selected-temp-status', 0);
                    }
                }
            })
        }
    }).mouseup(function() {
        timequantumClick = false;
        if (timequentumMouseType == 1) {
            timequentumStartElement.removeClass('time_quantum_grain_blue')
            timequentumStartElement.data('selected-status', 0);
        } else {
            timequentumStartElement.addClass('time_quantum_grain_blue')
            timequentumStartElement.data('selected-status', 1);
        }
        $('.time_quantum_grain_blue').data('selected-temp-status', 0);
        var selectedTimes = {
            1: [],
            2: [],
            3: [],
            4: [],
            5: [],
            6: [],
            7: []
        };
        $.each($('.time_quantum_grain_blue'), function(ink, inv) {
            let dateDay = $(this).parent().data('week');
            selectedTimes[dateDay].push($(this).data('time-num'));
        });
        $('.time_quantum_selected').hide();
        $.each(selectedTimes, function(ink, inv) {
            if (inv.length > 0) {
                var limitVal = -1;
                var timestr = '';
                for (var i = 0; i < inv.length; i++) {
                    if (inv[i] <= limitVal) {
                        continue;
                    }
                    var start = inv[i];
                    var end = start + 1;
                    var preNum = inv[i];
                    for (var j = (i + 1); j < inv.length; j++) {
                        if (inv[j] - preNum == 1) {
                            end = inv[j] + 1;
                            preNum = inv[j];
                            limitVal = inv[j];
                        }
                    }
                    timestr += '<span>' + getTimestr(start) + '~' + getTimestr(end) + '</span>';
                }
                $('#quantum_selected_times_' + ink).html(timestr);
                $('.time_quantum_selected').show();
                $('.quantum_selected_' + ink).show();
            } else {
                $('#quantum_selected_times_' + ink).empty();
                $('.quantum_selected_' + ink).hide();
            }
        });
    });
    $('.tap_box').mouseup(function() {
        timequantumClick = false;
    })

    function getTimestr(timeNum) {
        let times = timeNum / 2;
        let timeresArr = times.toString().split('.');
        let hours = timeresArr[0].toString();
        var minue = '00';
        if (timeresArr.length > 1) {
            minue = '30';
        }
        return hours + ':' + minue;
    }

    //清空时间段
    $('.time_quantum_clean_btn').click(function() {
        $('.time_quantum_selected').hide()
        $('.time_quantum_grain').removeClass('time_quantum_grain_blue')
        $('.qst').html('')
    })
};
Royui.prototype.upload = function($options) {
    $('head').append([
        '<style type="text/css">',
        '.royui-upload-select{border-radius:5px;outline:none;border:1px solid #ccc;min-width:100px;height:30px}',
        '.royui-upload-btn{border-radius:5px;outline:none;border:1px solid #ccc;width:50px;height:25px;margin-left:10px}',
        '.upload_item{width:100%;height:26px;line-height:26px}',
        '.progress_div{width:100%;height:8px;border:1px solid #EE99BB;background:#ffffff;margin-top:10px;border-radius:5px}',
        '.progress_bar{width:2px;height:8px;background:#EE99BB}',
        '.upload_btn_disable{background-image:url("/static/loading/w4.gif");background-size:cover;color:#ffffff}',
        '.jg{width:100%;height:6px}',
        '.close{display:none;width:16px;height:16px;line-height:16px;margin-left:20px;font-size:12px;color:#ffffff;font-weight:bolder;background:#ffaa99;text-align:center;border-radius:8px;cursor:pointer}',
        '.too_big{font-size: 12px;color: #ff5500;margin-left:30px}',
        '</style>'
    ].join(''));
    let $config = {
        auto: $options.auto ?? true,
        method: $options.message ?? 'post',
        fileType: $options.fileType ?? '*',
        buttonText: $options.buttonText ?? 'Select Files',
        buttonClass: $options.buttonClass ?? false,
        fileObjName: $options.fileObjName ?? 'Filedata',
        fileSizeLimit: $options.fileSizeLimit ?? '0',
        multi: $options.multi ?? false,
        limit: $options.limit ?? 0,
        formData: $options.formData ?? {},
        uploadScript: $options.uploadScript,
        onUploadComplete: $options.onUploadComplete ?? undefined,
        onError: $options.onError ?? undefined
    };
    let $elem = this.elem;
    $($elem).css('display', 'none')
    if ($config.fileType !== '*') {
        let $fileType = $config.fileType.split(','), $typeStr = '';
        $($fileType).each(function($i, $v) {
            let $idx = $v.indexOf('.');
            if ($idx < 0) {
                $typeStr += (',.' + $v)
            } else {
                $typeStr += (',' + $v.substr($idx))
            }
        });
        $typeStr = $typeStr.substring(1)
        $($elem).attr('accept', $typeStr)
    }
    if ($config.multi) {
        $($elem).attr('multiple', 'multiple')
    }
    let $obj = document.createElement('input');
    $($obj).attr('type', 'button');
    $($obj).val($config.buttonText);
    if ($config.buttonClass !== false) {
        $($obj).addClass($config.buttonClass)
    } else {
        $($obj).addClass('royui-upload-select')
    }
    let $parent = $($elem).parent(), $btn = null;
    $parent.append($obj);
    if (!$config.auto) {
        $btn = document.createElement('input');
        $($btn).attr('type', 'button').val('上传').addClass('royui-upload-btn');
        $parent.append($btn)
    }
    let $jg = document.createElement('div');
    $($jg).addClass('jg');
    $parent.append($jg);
    $($obj).click(function() {
        $($elem).click()
    });
    let $count = 0, $files = [], $progress_div = null;
    $($elem).change(function() {
        let $len = this.files.length;
        if (!$config.multi || ($config.limit > 0 && $count + $len > $config.limit)) {
            $files = [];
            $count = 0;
            $parent.children('div').remove()
        }
        $count += $len;
        let $size = $config.fileSizeLimit.toString();
        $size = $size.toLowerCase();
        if ($size.indexOf('m') > 0) {
            $size = parseFloat($size.substring(0, $size.length - 1));
            $size = $size * 1024 * 1024
        } else if ($size.indexOf('k') > 0) {
            $size = parseFloat($size.substring(0, $size.length - 1));
            $size = $size * 1024
        } else if ($size.indexOf('kb') > 0) {
            $size = parseFloat($size.substring(0, $size.length - 2));
            $size = $size * 1024
        } else if ($size.indexOf('b') > 0) {
            $size = parseFloat($size.substring(0, $size.length - 1));
        } else {
            $size = parseFloat($size)
        }
        $(this.files).each(function($i, $v) {
            if ($config.limit <= 0 || $i < $config.limit) {
                let $div = document.createElement('div');
                $($div).addClass('upload_item');
                if ($size <= 0 || $v.size <= $size) {
                    $files.push($v);
                    $($div).html(`${$v.name}<span class="close" data-filename="${$v.name}">✖</span>`);
                    $($div).mouseover(function() {
                        $(this).find('.close').css('display', 'inline-block')
                    }).mouseleave(function() {
                        $(this).find('.close').css('display', 'none')
                    })
                } else {
                    $count -= 1;
                    $($div).html($v.name + '<span class="too_big">尺寸过大，不会上传该文件</span>');
                }
                if ($progress_div === null) {
                    $parent.append($div)
                } else {
                    $($progress_div).before($div)
                }
            }
        });
        if ($progress_div === null && $count >= 1 && $len > 0) {
            $progress_div = document.createElement('div');
            let $progress_bar = document.createElement('div');
            $($progress_div).addClass('progress_div');
            $($progress_bar).addClass('progress_bar');
            $progress_div.append($progress_bar);
            $parent.append($progress_div);
        }
        if ($config.auto) {
            let $form = new FormData();
            if ($count > 1) {
                $($files).each(function($i, $v) {
                    $form.append($config.fileObjName + '[]', $v);
                });
            } else {
                $form.append($config.fileObjName, $files[0]);
            }
            $form.append('fileType', $config.fileType);
            for (let $i in $config.formData) {
                if (Array.isArray($config.formData[$i])) {
                    $config.formData[$i].forEach(($v, $ii) => {
                        $form.append(`${$i}[${$ii}]`, $v)
                    })
                } else {
                    $form.append($i, $config.formData[$i]);
                }
            }
            let $xhr = new XMLHttpRequest();
            $xhr.open($config.method, $config.uploadScript, true);
            $xhr.upload.addEventListener('progress', function(e) {
                progress(e)
            }, false);
            $xhr.onreadystatechange = function() {
                if ($xhr.readyState === 4) {
                    if ($xhr.status === 200) {
                        if (typeof $config.onUploadComplete === 'function') {
                            let $info = JSON.parse($xhr.responseText);
                            $config.onUploadComplete($info)
                        }
                    } else {
                        if (typeof $config.onError === 'function') {
                            $config.onError($xhr.responseText)
                        }
                    }
                }
            }
            $xhr.send($form);
        }
    });
    if ($btn !== null) {
        $($btn).click(function() {
            if ($count < 1) {
                layer.msg('请选择要上传的文件', {
                    icon: 2,
                    time: 1000
                });
                return false
            }
            let $this = $(this);
            $this.prop('disabled', 'disabled').addClass('upload_btn_disable');
            let $form = new FormData();
            if ($count > 1) {
                $($files).each(function($i, $v) {
                    $form.append($config.fileObjName + '[]', $v);
                });
            } else {
                $form.append($config.fileObjName, $files[0]);
            }
            $form.append('fileType', $config.fileType);
            for (let $i in $config.formData) {
                if (Array.isArray($config.formData[$i])) {
                    $config.formData[$i].forEach(($v, $ii) => {
                        $form.append(`${$i}[${$ii}]`, $v)
                    })
                } else {
                    $form.append($i, $config.formData[$i]);
                }
            }
            let $xhr = new XMLHttpRequest();
            $xhr.open($config.method, $config.uploadScript, true);
            $xhr.upload.addEventListener('progress', function(e) {
                progress(e)
            }, false);
            $xhr.onreadystatechange = function() {
                if ($xhr.readyState === 4) {
                    $files = [];
                    $count = 0;
                    if ($xhr.status === 200) {
                        $this.removeAttr('disabled').removeClass('upload_btn_disable');
                        if (typeof $config.onUploadComplete === 'function') {
                            let $info = JSON.parse($xhr.responseText);
                            $config.onUploadComplete($info)
                        }
                    } else {
                        $this.removeAttr('disabled').removeClass('upload_btn_disable');
                        if (typeof $config.onError === 'function') {
                            $config.onError($xhr.responseText)
                        }
                    }
                }
            }
            $xhr.send($form);
        })
    }
    $parent.on('click', '.close', function() {
        let $fname = $(this).data('filename');
        $($files).each(function($i, $v) {
            if ($v.name === $fname) {
                $files.splice($i, 1);
                $count -= 1;
            }
        });
        $(this).parent().remove();
        if ($files.length <= 0) {
            $('.progress_div').remove()
        }
    })
}
let progress = function(e) {
    let $percent;
    if (e.lengthComputable) {
        $percent = Math.round((e.loaded / e.total) * 100);
    }
    $('.progress_bar').css('width', $percent + '%');
    if ($percent === 100) {
        setTimeout(function() {
            $('.progress_div').hide(2000)
        }, 5000);
    }
}
Royui.prototype.edititem = function($options) {
    let $config = {
        url: $options.url, // ajax 修改数据 URL
        param: $options.param ?? null, // 发送到服务端的参数({id: 'id值'})
        onUpdated: $options.onUpdated ?? undefined // 修改成功后的回调函数
    };
    $('head').append([
        '<style type="text/css">',
        '.roy_edit_item{display: block;cursor: pointer;width: 50px;height: 20px;position: relative}',
        '.roy_edit_item:before{display: block;content: "♂";position: absolute;right: 0;color: #FFFFFF;bottom: 1px}',
        '.roy_edit_item:after{display: block;content: "♂";position: absolute;right: 0;color: #0000ff;bottom: 0}',
        '.roy_txt{height: 30px;outline: none;border: 1px solid #19aa8d;padding: 0;margin: 0;text-indent: 5px}',
        '.roy_radio{width: 20px;height: 20px;appearance: none;outline: none;position: relative}',
        '.roy_radio:before{content: "";width: 15px;height: 15px;border: 1px solid #19aa8d;display: inline-block;border-radius: 50%;vertical-align: middle}',
        '.roy_radio:checked:after{content: "";width: 9px;height: 9px;text-align: center;background: #19aa8d;border-radius: 50%;display: block;position: absolute;top: 4px;left: 4px}',
        '.roy_checkbox{width: 20px;height: 20px;appearance: none;outline: none;position: relative}',
        '.roy_checkbox:before{content: "";width: 15px;height: 15px;border: 1px solid #19aa8d;display: inline-block;vertical-align: middle}',
        '.roy_checkbox:checked:after{content: "";width: 9px;height: 9px;text-align: center;background: #19aa8d;display: block;position: absolute;top: 4px;left: 4px}',
        '</style>'
    ].join(''));
    $(this.elem).each(function() {
        let $this = $(this);
        $this.addClass('roy_edit_item');
        let $val = $this.text(),
            $len = $val.length,
            $size = parseInt($this.css('font-size')),
            $num = 0;
        if (!isNaN($val)) {
            $len = $len / 2
        }
        $this.width(($len * $size + 15) + 'px');
        $this.click(function() {
            let $type = $this.data('type'),
                $name = $this.data('name'),
                $text = $this.text(),
                $url = $this.data('url') ?? $config.url;
            if ($type === 'text') {
                let $txt = document.createElement('input');
                $txt.type = 'text';
                $txt.className = 'roy_txt';
                $txt.name = $name;
                $this.parent().append($txt);
                $this.css('display', 'none');
                $($txt).val($text).width($this.width() * 2 + 'px').select().blur(function() {
                    let $new_val = $($txt).val(),
                        $new_len = $new_val.length,
                        $param = JSON.parse(JSON.stringify($config.param));
                    if ($new_val !== $text) {
                        $param[$name] = $new_val;
                        console.log($param)
                        $.ajax({
                            type: 'post',
                            dataType: 'json',
                            cache: false,
                            url: $url,
                            data: $param,
                            success: function($data) {
                                if (typeof $config.onUpdated === 'function') {
                                    $config.onUpdated($data, $param, $this)
                                } else {
                                    window.location.reload();
                                }
                            }
                        })
                    }
                    $($txt).remove();
                    $this.text($new_val).css({
                        'display': 'block',
                        'width': ($new_len * $size + 15) + 'px'
                    })
                }).keydown(function(e) {
                    if (e.keyCode === 13) {
                        $($txt).blur()
                    }
                });
            } else if ($type === 'radio') {
                let $values = $this.data('values');
                if ($values === undefined || $values === '') {
                    let $values_url = $this.data('values_url');
                    if ($values_url === undefined || $values_url === '') {
                        alert('没有数据源');
                        return false
                    }
                    $.ajax({
                        type: 'get',
                        dataType: 'json',
                        cache: false,
                        async: false,
                        url: $values_url,
                        success: function($data) {
                            $values = $data
                        }
                    })
                }
                $($values).each(function($i, $v) {
                    let $radio = document.createElement('input'),
                        $id = $name + $v.value,
                        $label = document.createElement('label');
                    $radio.type = 'radio';
                    $radio.id = $id;
                    $radio.name = $name;
                    $radio.value = $v.value;
                    $radio.className = 'roy_radio';
                    if ($text === $v.txt) {
                        $radio.checked = true;
                    }
                    $this.parent().append($radio);
                    $($label).attr('for', $id).css('padding', '0 10px 0 2px').text($v.txt);
                    $this.parent().append($label);
                });
                $this.css('display', 'none');
                $('[name="' + $name + '"]').on('click', function() {
                    let $tv = $(this).next('label').text(),
                        $param = JSON.parse(JSON.stringify($config.param));
                    if ($tv !== $text) {
                        $param[$name] = $(this).val();
                        console.log($param)
                        $.ajax({
                            type: 'post',
                            dataType: 'json',
                            cache: false,
                            url: $url,
                            data: $param,
                            success: function($data) {
                                if ($data.code === 0 || $data.code === 200 || $data.status === 0 || $data.status === 200) {
                                    layer.msg('修改成功', {
                                        icon: 5,
                                        time: 1000
                                    })
                                }
                            }
                        })
                    }
                    $this.text($tv).css('display', 'block');
                    $('[name="' + $name + '"]').each(function() {
                        $(this).next('label').remove();
                        $(this).remove();
                    });
                });
            } else if ($type === 'select') {
                let $values = $this.data('values'), $select = document.createElement('select');
                if ($values === undefined || $values === '') {
                    let $values_url = $this.data('values_url');
                    if ($values_url === undefined || $values_url === '') {
                        alert('没有数据源');
                        return false
                    }
                    $.ajax({
                        type: 'get',
                        dataType: 'json',
                        cache: false,
                        async: false,
                        url: $values_url,
                        success: function($data) {
                            $values = $data
                        }
                    })
                }
                let $val = $this.text(),
                    $len = $val.length,
                    $size = parseInt($this.css('font-size'));
                $select.name = $name;
                $select.id = $name;
                $select.className = 'roy_txt';
                $select.style.width = ($len * $size + 38) + 'px';
                $($values).each(function($i, $v) {
                    let $option = document.createElement('option');
                    $option.value = $v.value;
                    $option.text = $v.txt;
                    if ($v.txt === $text) {
                        $option.selected = true;
                    }
                    $($select).append($option)
                });
                $this.css('display', 'none');
                $this.parent().append($select);
                $($select).focus().blur(function() {
                    $(this).remove();
                    $this.css('display', 'block');
                }).change(function() {
                    let $tv = $(this).find('option:selected').text(), $param = JSON.parse(JSON.stringify($config.param));
                    if ($tv !== $text) {
                        $param[$name] = $(this).val();
                        console.log($param)
                        $.ajax({
                            type: 'post',
                            dataType: 'json',
                            cache: false,
                            url: $url,
                            data: $param,
                            success: function($data) {
                                if ($data.code === 0 || $data.code === 200 || $data.status === 0 || $data.status === 200) {
                                    layer.msg('修改成功', {
                                        icon: 5,
                                        time: 1000
                                    })
                                }
                            }
                        })
                    }
                    $this.text($tv).css('display', 'block');
                    $(this).remove();
                });
            } else if ($type === 'checkbox') {
                let $values = $this.data('values');
                if ($values === undefined || $values === '') {
                    let $values_url = $this.data('values_url');
                    if ($values_url === undefined || $values_url === '') {
                        alert('没有数据源');
                        return false
                    }
                    $.ajax({
                        type: 'get',
                        dataType: 'json',
                        cache: false,
                        async: false,
                        url: $values_url,
                        success: function($data) {
                            $values = $data
                        }
                    })
                }
                $($values).each(function($i, $v) {
                    let $checkbox = document.createElement('input'),
                        $id = $name + $v.value,
                        $label = document.createElement('label');
                    $checkbox.type = 'checkbox';
                    $checkbox.id = $id;
                    $checkbox.name = $name;
                    $checkbox.value = $v.value;
                    $checkbox.className = 'roy_checkbox';
                    if ($text.indexOf($v.txt) >= 0) {
                        $checkbox.checked = true;
                    }
                    if ($text === $v.txt) {
                        $checkbox.checked = true;
                    }
                    $this.parent().append($checkbox);
                    $($label).attr('for', $id).css('padding', '0 10px 0 2px').text($v.txt);
                    $this.parent().append($label);
                });
                $this.css('display', 'none');
                let $valArr = $this.data('old_value') ?? [];
                let $aihaoArr = $text.split(','), $flag = false;
                if ($num === 0) {
                    $num = 1;
                }
                if ($num === 1) {
                    $num = 2;
                    $(document).click(function(e) {
                        let $elem = e.target;
                        if ($($elem).is('.roy_checkbox') || $($elem).is('label')) {
                            $flag = true;
                            if ($($elem).is(':checked')) {
                                let $idx = $aihaoArr.length;
                                $aihaoArr[$idx] = $($elem).next('label').text();
                                $valArr[$idx] = $($elem).val();
                            } else {
                                $aihaoArr = $aihaoArr.filter((el) => el !== $($elem).next('label').text());
                                $valArr = $valArr.filter((em) => em !== $($elem).val());
                            }
                        } else if ($flag) {
                            $flag = false;
                            $this.text($aihaoArr.join(','));
                            $('[name="' + $name + '"]').each(function() {
                                $(this).next('label').remove();
                                $(this).remove();
                            });
                            let $param = $config.param;
                            $param[$name] = $valArr;
                            let $new_len = $aihaoArr.toString().length;
                            $this.css({
                                'display': 'block',
                                'width': ($new_len * $size + 15) + 'px'
                            });
                            $.ajax({
                                type: 'post',
                                dataType: 'json',
                                cache: false,
                                url: $url,
                                data: $param,
                                success: function($data) {
                                    if ($data.code === 0 || $data.code === 200 || $data.status === 0 || $data.status === 200) {
                                        layer.msg('修改成功', {
                                            icon: 5,
                                            time: 1000
                                        })
                                    }
                                }
                            })
                        }
                    })
                }
            }
        });
    });
}

function royui(obj = null) {
    return new Royui(obj)
}